package com.amkai.aes.webservice.binary.objecthandler.inventory;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;

import com.amkai.aes.aescommon.inventory.InventorySearchParam;
import com.amkai.aes.aescommon.service.binary.job.inventory.InventoryElementHistoryInfo;
import com.amkai.aes.generatedbeans.cdmcasehistory.SupplyUsageKind;
import com.amkai.aes.generatedbeans.cdmcasehistory.logdetails.resources.AdjustmentDescriptor;
import com.amkai.aes.generatedbeans.cdmcasehistory.logdetails.resources.TransactionDescriptor;
import com.amkai.aes.generatedbeans.dictionary.ItemKind;
import com.amkai.aes.generatedbeans.inventory.InventoryElement;
import com.amkai.aes.generatedbeans.inventory.TransactionCalculationEffect;
import com.amkai.common.extensions.hibernate.config.manager.SessionManager;

public class AdjustmentHistoryHelper {

	@SuppressWarnings("unchecked")
	public static List<InventoryElementHistoryInfo> getAdjustmentDescriptorPageForHistory(SessionManager sm, InventorySearchParam searchParam)
			throws Exception {
		Long c = null;
		int count = 0;
		List<InventoryElementHistoryInfo> result = new ArrayList<InventoryElementHistoryInfo>();
		List<AdjustmentDescriptor> adjustmentDescriptors = null;
		InventoryElement ie = sm.get(InventoryElement.class, searchParam.getInventoryElementId());

		ItemKind itk = ie.getSupplyResourceItem().getKind();
		switch (itk) {
		case SUPPLY_RESOURCE_EQUIPMENT_ITEM:
		case SUPPLY_RESOURCE_INSTRUMENT_ITEM:
			c = (Long) sm.execute(" SELECT COUNT(ad) FROM AdjustmentDescriptor ad WHERE  ad.kindWrapper != " + SupplyUsageKind.PHYSICAL_INVENTORY_STATE.ordinal() 
					+ " AND ad.inventoryElement.id = :ieid ").setLong("ieid",
					searchParam.getInventoryElementId()).uniqueResult();
			if (c != null) {
				count = c.intValue();
			} else {
				count = 0;
			}
			if (count != searchParam.getQuerySize()) {
				searchParam.setFirstPosition(0);
			}
			
			adjustmentDescriptors = sm.execute(" FROM AdjustmentDescriptor ad WHERE ad.kindWrapper != " + SupplyUsageKind.PHYSICAL_INVENTORY_STATE.ordinal() 
					+ " AND  ad.inventoryElement.id = :ieid order by ad ASC").setLong("ieid",
					searchParam.getInventoryElementId()).setFirstResult(searchParam.getFirstPosition()).setMaxResults(searchParam.getPageSize()).list();
			Collections.sort(adjustmentDescriptors, new Comparator<AdjustmentDescriptor>() {

				@Override
				public int compare(AdjustmentDescriptor o1, AdjustmentDescriptor o2) {
					// TODO Auto-generated method stub
					if (o1.getAdjustment() != null) {
						if (o2.getAdjustment() != null) {
							return o1.getAdjustment().getDate().compareTo(o2.getAdjustment().getDate());
						} else {
							return o1.getAdjustment().getDate().compareTo(o2.getAdjustmentDate());
						}
					} else {
						if (o2.getAdjustment() != null) {
							return o1.getAdjustmentDate().compareTo(o2.getAdjustment().getDate());
						} else {
							return o1.getAdjustmentDate().compareTo(o2.getAdjustmentDate());
						}
					}

				}

			});

			break;
		case SUPPLY_RESOURCE_ITEM:
		case SUPPLY_RESOURCE_MEDICATION_ITEM:
			c = (Long)sm
			.execute(
					" SELECT COUNT(ad) FROM AdjustmentDescriptor ad WHERE ad.inventoryElement.id = :ieid and ad.adjustment is not null")
			.setLong("ieid", searchParam.getInventoryElementId())
			// .setMaxResults(searchParam.getQuerySize())
			.uniqueResult();
			if (c != null) {
				count = c.intValue();
			} else {
				count = 0;
			}
			if (count != searchParam.getQuerySize()) {
				searchParam.setFirstPosition(0);
			}
			adjustmentDescriptors = sm
					.execute(
							" SELECT ad FROM AdjustmentDescriptor ad WHERE ad.inventoryElement.id = :ieid and ad.adjustment is not null order by ad.adjustment ASC")
					.setLong("ieid", searchParam.getInventoryElementId())
					// .setMaxResults(searchParam.getQuerySize())
					.setFirstResult(searchParam.getFirstPosition()).setMaxResults(searchParam.getPageSize()).list();

			break;
		}

		
		for (AdjustmentDescriptor ad : adjustmentDescriptors) {
			InventoryElementHistoryInfo iehi = new InventoryElementHistoryInfo();
			iehi.adjustmentDescriptorId = ad.getId();
			iehi.adjustmentDate = ad.getAdjustmentDate();
			if (ad.getTransactionCode().getCalculationEffect().equals(TransactionCalculationEffect.SUBTRACT)) {
				iehi.substract = ad.getTransactionCode().getName();
				iehi.substractQ = ad.getQuantity();
			} else {

				iehi.add = ad.getTransactionCode().getName();
				iehi.addQ = ad.getQuantity();

			}

			TransactionDescriptor td = getLastTransactionDescriptor(sm, ad);
			if (td != null && td.getInventoryValueLog() != null){
				iehi.qoh = td.getInventoryValueLog().getQoh();				
			}else{
				Integer qoh = (Integer) sm.execute(	"SELECT td.inventoryValueLog.qoh FROM TransactionDescriptor td  "+ 
							"WHERE td.adjustmentDescriptor.adjustment is not null AND " + 
							"td.adjustmentDescriptor.adjustment.date < :adid  AND td.adjustmentDescriptor.inventoryElement = :ie AND td.inventoryValueLog is not NULL ORDER BY  td.inventoryValueLog DESC ")
							.setMaxResults(1)
							.setDate("adid", ad.getAdjustmentDate())
							.setEntity("ie", ad.getInventoryElement())
							.uniqueResult();
				iehi.qoh = qoh;
			}
			if (c != null){
				iehi.querySize = count;
			}
			result.add(iehi);
		}
		return result;
	}

	private static TransactionDescriptor getLastTransactionDescriptor(SessionManager sm, AdjustmentDescriptor ad) throws Exception {
		// AES-17925 - order by InventoryValueLog.id
		TransactionDescriptor result = null;
		Long tdid = (Long) sm.execute(" SELECT td.id FROM TransactionDescriptor td WHERE td.adjustmentDescriptor = :ad AND td.inventoryValueLog.id = (SELECT MAX(tdv.inventoryValueLog.id) FROM TransactionDescriptor tdv WHERE tdv.adjustmentDescriptor = td.adjustmentDescriptor)").setEntity("ad", ad)
				.uniqueResult();
		result = sm.get(TransactionDescriptor.class, tdid);
		return result;
	}

}
